package cn.schoolwow.quickflow.service.quickFlow.putData;

import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.domain.FlowConfig;
import cn.schoolwow.quickflow.domain.FlowDataFeature;

import java.util.HashMap;
import java.util.Map;

public class QuickFlowPutDataOperationImpl implements QuickFlowPutDataOperation {
    private FlowConfig flowConfig;

    public QuickFlowPutDataOperationImpl(FlowConfig flowConfig) {
        this.flowConfig = flowConfig;
    }

    @Override
    public QuickFlow putContextThreadLocalData(String key, Object value, FlowDataFeature... flowDataFeatures) {
        boolean skipExistData = FlowDataFeature.containFeature(FlowDataFeature.SkipExistData, flowDataFeatures);
        boolean temporaryData = FlowDataFeature.containFeature(FlowDataFeature.TemporaryData, flowDataFeatures);
        ThreadLocal<Map<String,Object>> threadLocal = flowConfig.flowConfigDataContext.threadLocalDataMap;
        if(null==threadLocal.get()){
            threadLocal.set(new HashMap<>());
        }
        Map<String,Object> contextThreadLocalMap = threadLocal.get();
        if(skipExistData){
            contextThreadLocalMap.putIfAbsent(key, value);
        }else{
            contextThreadLocalMap.put(key, value);
        }
        if(temporaryData){
            flowConfig.flowConfigDataContext.flowContextDataKeySet.temporaryDataKeySet.add(key);
        }
        return flowConfig.quickFlow;
    }

    @Override
    public QuickFlow putContextThreadLocalInstanceData(Object instance, FlowDataFeature... flowDataFeatures) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = instance.getClass().getName();
        return putContextThreadLocalData(key, instance, flowDataFeatures);
    }

    @Override
    public QuickFlow putContextThreadLocalInstanceData(Object instance, Class clazz, FlowDataFeature... flowDataFeatures) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = clazz.getName();
        return putContextThreadLocalData(key, instance, flowDataFeatures);
    }

    @Override
    public QuickFlow putContextThreadLocalDataMap(Map<String, Object> dataMap, FlowDataFeature... flowDataFeatures) {
        if(null==dataMap||dataMap.isEmpty()){
            return flowConfig.quickFlow;
        }
        for(String key:dataMap.keySet()){
            Object value = dataMap.get(key);
            putContextThreadLocalData(key, value);
        }
        return flowConfig.quickFlow;
    }

    @Override
    public QuickFlow putContextTemporaryData(String key, Object value) {
        return putContextData(key, value, FlowDataFeature.TemporaryData);
    }

    @Override
    public QuickFlow putContextTemporaryInstanceData(Object instance) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = instance.getClass().getName();
        return putContextTemporaryData(key, instance);
    }

    @Override
    public QuickFlow putContextTemporaryInstanceData(Object instance, Class clazz) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = clazz.getName();
        return putContextTemporaryData(key, instance);
    }

    @Override
    public QuickFlow putContextTemporaryDataMap(Map<String, Object> dataMap) {
        if(null==dataMap||dataMap.isEmpty()){
            return flowConfig.quickFlow;
        }
        for(String key:dataMap.keySet()){
            Object value = dataMap.get(key);
            putContextData(key, value);
        }
        return flowConfig.quickFlow;
    }

    @Override
    public QuickFlow putContextData(String key, Object value, FlowDataFeature... flowDataFeatures) {
        boolean skipExistData = FlowDataFeature.containFeature(FlowDataFeature.SkipExistData, flowDataFeatures);
        boolean temporaryData = FlowDataFeature.containFeature(FlowDataFeature.TemporaryData, flowDataFeatures);

        if(skipExistData){
            flowConfig.flowConfigDataContext.dataMap.putIfAbsent(key, value);
        }else{
            flowConfig.flowConfigDataContext.dataMap.put(key, value);
        }
        if(temporaryData){
            flowConfig.flowConfigDataContext.flowContextDataKeySet.temporaryDataKeySet.add(key);
        }
        return flowConfig.quickFlow;
    }

    @Override
    public QuickFlow putContextInstanceData(Object instance, FlowDataFeature... flowDataFeatures) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = instance.getClass().getName();
        return putContextData(key, instance, flowDataFeatures);
    }

    @Override
    public QuickFlow putContextInstanceData(Object instance, Class clazz, FlowDataFeature... flowDataFeatures) {
        if(null==instance){
            return flowConfig.quickFlow;
        }
        String key = clazz.getName();
        return putContextData(key, instance, flowDataFeatures);
    }

}
